package cz.muni.fi.pa165.sme.services.impl;

import java.util.ArrayList;
import java.util.List;

import cz.muni.fi.pa165.sme.api.SportActivityService;
import cz.muni.fi.pa165.sme.api.to.SportActivityTO;
import cz.muni.fi.pa165.sme.common.TOValidator;
import cz.muni.fi.pa165.sme.dao.api.SportActivityDao;
import cz.muni.fi.pa165.sme.dao.entity.SportActivity;
import cz.muni.fi.pa165.sme.exceptions.ServiceException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.convert.ConversionService;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author Martin Novak
 */
@Service
public class SportActivityServiceImpl implements SportActivityService {

	private static final String ID_NULL = "Id cannot be null";
	private static final String NULL_OBJECT_MESSAGE = "Parameter cannot be null";
	private static final String ID_NOT_NULL = "Id must not be set";

	@Autowired
	private SportActivityDao sportActivityDao;

	@Autowired
	@Qualifier("conversionService")
	private ConversionService conversionService;

	@Override
	@PreAuthorize("hasRole('USER')")
	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void createSportActivity(final SportActivityTO sportActivityTO) {
		TOValidator.validateObjectNotNull(sportActivityTO, NULL_OBJECT_MESSAGE);
		TOValidator.validateIdNull(sportActivityTO.getId(), ID_NOT_NULL);

		final SportActivity sportActivity = conversionService.convert(sportActivityTO, SportActivity.class);

		sportActivityDao.createSportActivity(sportActivity);

		if (sportActivity.getId() == null) {
			throw new ServiceException("ID was not assigned");
		}

		sportActivityTO.setId(sportActivity.getId());
	}

	@Override
	@PreAuthorize("hasRole('USER')")
	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void updateSportActivity(final SportActivityTO sportActivityTO) {
		TOValidator.validateObjectNotNull(sportActivityTO, NULL_OBJECT_MESSAGE);
		TOValidator.validateObjectNotNull(sportActivityTO.getId(), ID_NULL);

		final SportActivity sportActivity = conversionService.convert(sportActivityTO, SportActivity.class);

		sportActivityDao.updateSportActivity(sportActivity);
	}

	@Override
	@PreAuthorize("hasRole('USER')")
	public SportActivityTO findSportActivityById(final Long id) {
		TOValidator.validateObjectNotNull(id, NULL_OBJECT_MESSAGE);
		final SportActivity sportActivity = sportActivityDao.findSportActivityById(id);

		return conversionService.convert(sportActivity, SportActivityTO.class);
	}

	@Override
	@PreAuthorize("hasRole('USER')")
	@Transactional(propagation = Propagation.REQUIRES_NEW)
	public void deleteSportActivity(final SportActivityTO sportActivityTO) {
		TOValidator.validateObjectNotNull(sportActivityTO, NULL_OBJECT_MESSAGE);
		TOValidator.validateObjectNotNull(sportActivityTO.getId(), ID_NULL);

		final SportActivity sportActivity = conversionService.convert(sportActivityTO, SportActivity.class);
		sportActivityDao.deleteSportActivity(sportActivity);
	}

	@Override
	@PreAuthorize("hasRole('USER')")
	public List<SportActivityTO> findAllSportActivities() {
		final List<SportActivity> sportActivityResult = sportActivityDao.findAllSportActivities();
		final List<SportActivityTO> sportActivityTOResult = new ArrayList<SportActivityTO>();

		for (SportActivity sportActivity : sportActivityResult) {
			sportActivityTOResult.add(conversionService.convert(sportActivity, SportActivityTO.class));
		}

		return sportActivityTOResult;
	}

	@Override
	public boolean exists(final SportActivityTO sportActivityTO) {
		TOValidator.validateObjectNotNull(sportActivityTO, NULL_OBJECT_MESSAGE);

		return sportActivityTO.getId() != null && sportActivityDao.findSportActivityById(sportActivityTO.getId()) != null;

	}

	@Override
	public boolean isReferenced(final SportActivityTO sportActivityTO) {
		TOValidator.validateObjectNotNull(sportActivityTO, NULL_OBJECT_MESSAGE);

		final SportActivity sportActivityOrig = conversionService.convert(sportActivityTO, SportActivity.class);

		final List<SportActivity> sportActivityList = sportActivityDao.findAllSportActivities();

		for (SportActivity sportActivity : sportActivityList) {
			if (sportActivity.equals(sportActivityOrig)) {
				return true;
			}
		}

		return false;
	}

	@Override
	public List<SportActivityTO> findSportActivityByTitle(final String title) {
		TOValidator.validateObjectNotNull(title, NULL_OBJECT_MESSAGE);
		final List<SportActivity> sportActivityResult = sportActivityDao.findSportActivityByTitle(title);
		final List<SportActivityTO> sportActivityTOResult = new ArrayList<SportActivityTO>();

		for (SportActivity sportActivity : sportActivityResult) {
			sportActivityTOResult.add(conversionService.convert(sportActivity, SportActivityTO.class));
		}

		return sportActivityTOResult;
	}
}
